package agency.sales ;

import java.net.URLEncoder ;
import java.util.Date ;
import java.util.Map ;
import java.util.Objects ;
import java.util.Properties ;
import java.util.TreeMap ;

import com.cybersource.ws.client.Client ;

import agency.Sales ;
import common.Card ;
import dict.AgencyDict ;
import dict.BcDict ;
import entities.TBank ;
import entities.TBc ;
import entities.TCard ;
import entities.TTransaction ;
import util.LogUtil ;
import utils.AesUtil ;
import utils.DateUtil ;
import utils.NumberUtil ;
import utils.StringUtil ;

public class C3dtst implements Sales
{

	private static String CURRENCY = "CNY" ;

	private static String keysDirectory = "d:\\Keys\\Cbypay\\product\\" ;

	private static String receiveHost = "http://localhost:4444/gateway/" ;

	private static String receivePath = receiveHost + "C3dtst" ;

	private static String sendToProduction = "false" ;

	private static String enableLog = "true" ;

	private static String logPah = "d:\\" ;

	static
	{
		if ( "linux".equalsIgnoreCase ( System.getProperty ( "os.name" ) ) )
		{
			keysDirectory = "/usr/local/tomcat9/" ;
			receiveHost = "https://gateway.atepay.com/" ;
			receivePath = receiveHost + "C3dtst" ;
			sendToProduction = "false" ;
			enableLog = "false" ;
			logPah = "/usr/logs/" ;
		}
	}

	private static String targetAPIVersion = "1.158" ;

	private static String numberOfRetries = "5" ;

	private static String retryInterval = "5" ;

	@SuppressWarnings ( "unchecked" )
	public void process (
			TBc bc ,
			TTransaction transaction ,
			TBank bank ,
			TCard card
	)
	{
		Map < String , String > requestMap = new TreeMap < String , String > ( ) ;
		Map < String , String > responseMap = new TreeMap < String , String > ( ) ;

		String referenceID = StringUtil.number ( 32 ) ;

		// 配置
		Properties cybsInfo = new Properties ( ) ;
		cybsInfo.put ( "merchantID" , bank.getBnkMer ( ) ) ;
		cybsInfo.put ( "keysDirectory" , keysDirectory ) ;
		cybsInfo.put ( "keyAlias" , bank.getBnkMer ( ) ) ;
		cybsInfo.put ( "keyPassword" , bank.getBnkMer ( ) ) ;
		cybsInfo.put ( "targetAPIVersion" , targetAPIVersion ) ;
		cybsInfo.put ( "sendToProduction" , sendToProduction ) ;
		cybsInfo.put ( "sendToAkamai" , "true" ) ;
		cybsInfo.put ( "useHttpClient" , "false" ) ;
		cybsInfo.put ( "allowRetry" , "true" ) ;
		cybsInfo.put ( "numberOfRetries" , numberOfRetries ) ;
		cybsInfo.put ( "retryInterval" , retryInterval ) ;
		cybsInfo.put ( "enableJdkCert" , "false" ) ;
		cybsInfo.put ( "enableCacert" , "false" ) ;
		cybsInfo.put ( "cacertPassword" , "" ) ;
		cybsInfo.put ( "useSignAndEncrypted" , "false" ) ;
		cybsInfo.put ( "timeout" , "1000" ) ;
		cybsInfo.put ( "enableLog" , enableLog ) ;
		cybsInfo.put ( "logDirectory" , logPah ) ;
		cybsInfo.put ( "logMaximumSize" , "10" ) ;
		cybsInfo.put ( "certificateCacheEnabled" , "true" ) ;

		// 验证
		requestMap.put ( "merchantReferenceCode" , bc.getBcNo ( ) ) ;
		requestMap.put ( "payerAuthEnrollService_run" , "true" ) ;
		requestMap.put ( "card_cardType" , Card.code ( card.getCrdType ( ) ) ) ;
		requestMap.put ( "referenceID" , referenceID ) ;

		requestMap.put ( "purchaseTotals_currency" , CURRENCY ) ;
		requestMap.put ( "item_0_unitPrice" , NumberUtil.transfer ( bc.getBcAmount ( ) ) ) ;
		try
		{
			String number = card.getCrdNumber ( ) ;
			String expire = AesUtil.AES_Decrypt ( AesUtil.KEY , card.getCrdExpire ( ) ) ;
			requestMap.put ( "card_accountNumber" , number ) ;
			requestMap.put ( "card_expirationMonth" , expire.substring ( 0 , 2 ) ) ;
			requestMap.put ( "card_expirationYear" , "20" + expire.substring ( 2 , 4 ) ) ;
		} catch ( Exception e )
		{
			e.printStackTrace ( ) ;
			bc.setBcMark ( "555" ) ;
			bc.setBcInfo ( "edc sale data encrpt exception" ) ;
			bc.setBcCode ( AgencyDict.C3D_ENCRYPT_EXCEPTION ) ;
			bc.setBcMessage ( AgencyDict.AGENCY.get ( AgencyDict.C3D_ENCRYPT_EXCEPTION ) ) ;
			return ;
		}

		requestMap.put ( "billTo_ipAddress" , card.getCrdIp ( ) ) ;
		requestMap.put ( "billTo_phoneNumber" , card.getCrdHphone ( ) ) ;
		requestMap.put ( "billTo_firstName" , card.getCrdHfname ( ) ) ;
		requestMap.put ( "billTo_lastName" , card.getCrdHlname ( ) ) ;
		requestMap.put ( "billTo_street1" , card.getCrdHaddr ( ) ) ;
		requestMap.put ( "billTo_city" , card.getCrdHcity ( ) ) ;
		requestMap.put ( "billTo_state" , card.getCrdHstate ( ) ) ;
		requestMap.put ( "billTo_postalCode" , card.getCrdHzip ( ) ) ;
		requestMap.put ( "billTo_country" , card.getCrdHcountry ( ) ) ;
		requestMap.put ( "billTo_email" , card.getCrdHemail ( ) ) ;

		requestMap.put ( "shipTo_firstName" , card.getCrdCfname ( ) ) ;
		requestMap.put ( "shipTo_lastName" , card.getCrdClname ( ) ) ;
		requestMap.put ( "shipTo_street1" , card.getCrdCaddr ( ) ) ;
		requestMap.put ( "shipTo_city" , card.getCrdCcity ( ) ) ;
		requestMap.put ( "shipTo_state" , card.getCrdCstate ( ) ) ;
		requestMap.put ( "shipTo_postalCode" , card.getCrdCzip ( ) ) ;
		requestMap.put ( "shipTo_country" , card.getCrdCcountry ( ) ) ;

		// 日志打印发送数据
		StringBuffer send = new StringBuffer ( ) ;
		for ( Map.Entry < String , String > e : requestMap.entrySet ( ) )
		{
			send.append ( e.getKey ( ) + "=" + e.getValue ( ) + "&" ) ;
		}
		LogUtil.agency ( bank.getBnkNo ( ).toUpperCase ( ) + "_ENROLL" , send.toString ( ) ) ;

		try
		{
			responseMap = Client.runTransaction ( requestMap , cybsInfo ) ;
		} catch ( Exception ex )
		{
			try
			{
				Thread.sleep ( 3000 ) ;
				responseMap = Client.runTransaction ( requestMap , cybsInfo ) ;
			} catch ( Exception e )
			{
				e.printStackTrace ( ) ;
				bc.setBcMark ( "555" ) ;
				bc.setBcInfo ( "c3dtst sale data encrpt exception" ) ;
				bc.setBcCode ( AgencyDict.C3D_TRANSMISSION_EXCEPTION ) ;
				bc.setBcMessage ( AgencyDict.AGENCY.get ( AgencyDict.C3D_TRANSMISSION_EXCEPTION ) ) ;
				return ;
			}

		}

		if ( Objects.isNull ( responseMap ) )
		{
			bc.setBcMark ( "555" ) ;
			bc.setBcInfo ( "c3dtst sale data response exception" ) ;
			bc.setBcCode ( AgencyDict.C3D_TRANSMISSION_EXCEPTION ) ;
			bc.setBcMessage ( AgencyDict.AGENCY.get ( AgencyDict.C3D_TRANSMISSION_EXCEPTION ) ) ;
			return ;
		}

		// 日志打印返回数据
		StringBuffer reve = new StringBuffer ( ) ;
		for ( Map.Entry < String , String > e : responseMap.entrySet ( ) )
		{
			reve.append ( e.getKey ( ) + "=" + e.getValue ( ) + "&" ) ;
		}
		LogUtil.agency ( bank.getBnkNo ( ).toUpperCase ( ) + "_ENROLL" , reve.toString ( ) ) ;

		if ( ! responseMap.containsKey ( "reasonCode" ) )
		{
			bc.setBcMark ( "555" ) ;
			bc.setBcInfo ( "c3dtst sale data parameter exception" ) ;
			bc.setBcCode ( AgencyDict.C3D_TRANSMISSION_EXCEPTION ) ;
			bc.setBcMessage ( AgencyDict.AGENCY.get ( AgencyDict.C3D_TRANSMISSION_EXCEPTION ) ) ;
			return ;
		}

		if ( responseMap.get ( "reasonCode" ).equals ( "100" ) )
		{
			new Cbytst ( ).process ( bc , transaction , bank , card ) ;
			return ;
		}

		if ( responseMap.get ( "reasonCode" ).equals ( "475" ) )
		{
			StringBuffer sb = new StringBuffer ( ) ;
			sb.append ( "<html><head></head><body onload=\"payerForm.submit();\">" ) ;
			sb.append ( "<form id=\"payerForm\" action=\"" + responseMap.get ( "payerAuthEnrollReply_acsURL" ) + "\"  method=\"POST\">" ) ;
			sb.append ( "<input type=\"hidden\" name = \"PaReq\" value=\"" + responseMap.get ( "payerAuthEnrollReply_paReq" ) + "\" />" ) ;
			sb.append ( "<input type=\"hidden\" name = \"TermUrl\" value=\"" + receivePath + "\" /> " ) ;
			sb.append ( "<input type=\"hidden\" name = \"MD\" value=\"" + bc.getBcNo ( ) + "\" /> " ) ;
			sb.append ( "</form>" ) ;
			sb.append ( "</body></html>" ) ;
			String message = "" ;
			try
			{
				message = AesUtil.AES_Encrypt ( AesUtil.KEY , sb.toString ( ) ) ;
				message = URLEncoder.encode ( message , "UTF-8" ) ;
			} catch ( Exception e )
			{
				e.printStackTrace ( ) ;
			}

			bc.setBcRef ( responseMap.get ( "payerAuthEnrollReply_authenticationTransactionID" ) ) ;
			bc.setBcCard ( card.getCrdFake ( ) ) ;
			bc.setBcTime ( DateUtil.format ( new Date ( ) , DateUtil.DATE ) ) ;
			bc.setBcMark ( StringUtil.space ( responseMap.get ( "reasonCode" ) ) ) ;
			bc.setBcInfo ( StringUtil.space ( responseMap.get ( "reasonCode" ) ) + StringUtil.quote ( responseMap.get ( "decision" ) ) ) ;
			bc.setBcCode ( BcDict.BC_AUTHENT ) ;
			bc.setBcMessage ( receiveHost + "Authentication?ref=" + bc.getBcNo ( ) + "&auth=" + message ) ;
			return ;
		}

		bc.setBcCard ( card.getCrdFake ( ) ) ;
		bc.setBcTime ( DateUtil.format ( new Date ( ) , DateUtil.DATE ) ) ;
		bc.setBcMark ( StringUtil.space ( responseMap.get ( "reasonCode" ) ) ) ;
		bc.setBcInfo ( StringUtil.space ( responseMap.get ( "reasonCode" ) ) + StringUtil.quote ( responseMap.get ( "decision" ) ) ) ;
		bc.setBcCode ( BcDict.BC_FAILURE ) ;
		bc.setBcMessage ( responseMap.get ( "decision" ) ) ;
		return ;
	}

	public static void main (
			String [ ] args
	) throws Exception
	{

	}
}
